import threading, pygame, random

class BallArea(threading.Thread):

    def __init__(self, width, height, leftwall = True, rightwall = True):

        random.seed()
        pygame.init()
        self.screen = pygame.display.set_mode((width, height))
        pygame.display.set_caption("pybanet")
        
        self.balls = []
        self.eballs = []
        self.rightwall = rightwall
        self.leftwall = leftwall
        self.perso_img = False
	self.caught_ball = False
        threading.Thread.__init__(self)

    def __del__(self):
        pygame.quit()

    def stop(self):
        self.go = False

    def run(self):
        
        print "BallArea thread started"
        self.go = True
        
        (scr_w, scr_h) = self.screen.get_size()

        background = pygame.Surface((scr_w, scr_h))
        background = background.convert()
        background.fill((0,0,0))

        dfont = pygame.font.SysFont("Arial", 12)
        
        clock = pygame.time.Clock()

        while self.go:
            
            txt = "%.2f fps" % (clock.get_fps())
            lbl = dfont.render(txt, 1, (255,255,0))

            self.screen.blit(background, (0,0))
            self.screen.blit(lbl, (2,2))

            for ball in self.balls:
                
                # move ball
                ball.x += ball.dx
                ball.y += ball.dy

                # detect edge collision
                if ball.y < 0:  # top
                    ball.y = 0
                    ball.dy *= -1

                elif ball.y + ball.h > scr_h: # bottom
                    ball.y = scr_h - ball.h
                    ball.dy *= -1

                elif ball.x < 0: # left
                    ball.x = 0
                    if not self.leftwall: 
                        self.eject(ball)
                    else:
                        ball.dx *= -1

                elif ball.x + ball.w > scr_w: # right
                    ball.x = scr_w - ball.w
                    if not self.rightwall: 
                        self.eject(ball)
                    else:
                        ball.dx *= -1

                #print ball_x, ball_dx, ball_y, ball_dy
                self.screen.blit(ball.surf, (ball.x, ball.y))

            # handle events
            for event in pygame.event.get():
		if event.type == pygame.QUIT:
		    self.go = False

		elif event.type == pygame.MOUSEBUTTONDOWN:
                    self.mousedown_pos = event.pos
                    if event.button == 1:
                        for ball in self.balls:
                            r = ball.get_rect()
                            if r.collidepoint(self.mousedown_pos):
                                ball.dx = 0
                                ball.dy = 0
                                self.caught_ball = ball

		elif event.type == pygame.MOUSEBUTTONUP:
                    (x,y) = self.mousedown_pos
                    dx = int(round((x - event.pos[0]) * -0.1))
                    dy = int(round((y - event.pos[1]) * -0.1))
                    
                    if event.button == 1 and self.caught_ball:
                        self.caught_ball.dx = dx
                        self.caught_ball.dy = dy
                        self.caught_ball = False
                    elif event.button == 3:
                        if self.perso_img:
                            b = Ball(self.perso_img, x, y, dx, dy)
                        else:
                            b = Ball("img/whiteball.png", x, y, dx, dy)
                        
                        print "mouse launch: %s @%dx%d +%dx%d" % (b.img_file,b.x,b.y,b.dx,b.dy)
                        self.balls.append(b)

		elif event.type == pygame.KEYDOWN:
		    
                    if event.key == pygame.K_ESCAPE:
			self.go = False

                    elif event.key == pygame.K_k:
                        if len(self.balls) > 0: self.balls.pop()

                    elif event.key == pygame.K_b:
                        self.inject_rnd("img/whiteball.png")

                    elif event.key == pygame.K_e:
                        self.inject_rnd("img/eyes.png")

                    elif event.key == pygame.K_p:
                        if self.perso_img:
                            self.inject_rnd(self.perso_img)

            clock.tick(100)
            pygame.display.flip()
        
	self.screen.blit(background, (0,0))
        pygame.display.flip()

    def inject(self, img_file, x, y, dx, dy):
        
        b = Ball(img_file, x, y, dx, dy)

        if b.x == 0:
            b.x = self.screen.get_size()[0] - b.w
        else:
            b.x = 0
        
        print "inject ball: %s @%dx%d +%dx%d" % (b.img_file,b.x,b.y,b.dx,b.dy)
        self.balls.append(b)

    def inject_rnd(self, img_file, max_v = 5):

        (max_x,max_y) = self.screen.get_size()
        x = random.randint(0, max_x)
        y = random.randint(0, max_y)
        dx = random.randint(1,max_v)
        dy = random.randint(1,max_v)
        b = Ball(img_file, x, y, dx, dy)
        print "inject ball: %s @%dx%d +%dx%d" % (b.img_file,b.x,b.y,b.dx,b.dy)
        self.balls.append(b)

    def eject(self, b):
        self.balls.remove(b)
        self.eballs.append(b)
        print "eject ball: @%dx%d +%dx%d" % (b.x,b.y,b.dx,b.dy)

    def get_ejected(self):
        if len(self.eballs) > 0:
            return self.eballs.pop(0)

class Ball:

    def __init__(self, img_file, x = 0, y = 0, dx = 1, dy = 1):

        self.img_file = img_file

        surf = pygame.image.load(img_file)
        self.surf = surf.convert()
        (self.w, self.h) = surf.get_size()

        self.x = x
        self.y = y
        self.dx = dx
        self.dy = dy
	
    def get_rect(self):
	return pygame.Rect(self.x,self.y,self.w,self.h)

def pump_events():
    pygame.event.pump()

def demo_balls(ba):
    ba.inject_rnd("img/eyes.png")
    ba.inject_rnd("img/whiteball.png")

if __name__ == "__main__":
    b = BallArea(640,480)
    demo_balls(b)
    b.start()
    while b.isAlive():
        pump_events()
